Melo's Blog

Android 6.0 运行时权限简洁封装

Android 6.0 运行时权限简洁封装

本文原创,转载请注明出处。
欢迎关注我的 简书 ,关注我的专题 Android Class 我会长期坚持为大家收录简书上高质量的 Android 相关博文。

写在前面:

Android M 中有一个比较重要的知识点就是运行时权限了,关于运行时权限的文章和封装库目前也出现了不少,在开发的过程中始终觉得运行时权限这块的代码可以进一步封装一下,让其使用起来能再简洁一点,并且还不容易出错。关于 Android 运行时权限的知识就不多讲解了,可以参考下面的一些资料:

Android Runtime Permissions

Android 6.0 运行时权限处理完全解析

知识点比较简单,大致了解和使用过后,就来开始我的这次封装之旅吧。

现在直观的看看封装之后的使用,是不是清爽很多?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@OnClick(R.id.tv_toolbar_right)
public void onClick() {
performRequestPermissions(getString(R.string.permission_desc), new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.ACCESS_COARSE_LOCATION}
, PER_REQUEST_CODE, new PermissionsResultListener() {
@Override
public void onPermissionGranted() {
Toast.makeText(MainActivity.this, "已申请权限", Toast.LENGTH_LONG).show();
}
@Override
public void onPermissionDenied() {
Toast.makeText(MainActivity.this, "拒绝申请权限", Toast.LENGTH_LONG).show();
}
});
}

我将运行时权限封装到 BaseActivity 中,MainActivty 继承BaseActivity,调用 performRequestPermissions 方法,此时我不用再去做一些判断,只需要穿入四个参数即可。当然你为了在 6.0 以下保证应用正常运行,你依然需要像以前一样,在清单文件中申明要使用的权限。

首先我需要一个接口做通信:

1
2
3
4
5
6
7
public interface PermissionsResultListener {
void onPermissionGranted();
void onPermissionDenied();
}

然后把逻辑代码封装在 BaseActivity 里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
public class BaseActivity extends AppCompatActivity {
private PermissionsResultListener mListener;
private int mRequestCode;
/**
* 其他 Activity 继承 BaseActivity 调用 performRequestPermissions 方法
*
* @param desc 首次申请权限被拒绝后再次申请给用户的描述提示
* @param permissions 要申请的权限数组
* @param requestCode 申请标记值
* @param listener 实现的接口
*/
protected void performRequestPermissions(String desc, String[] permissions, int requestCode, PermissionsResultListener listener) {
if (permissions == null || permissions.length == 0) {
return;
}
mRequestCode = requestCode;
mListener = listener;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkEachSelfPermission(permissions)) {// 检查是否声明了权限
requestEachPermissions(desc, permissions, requestCode);
} else {// 已经申请权限
if (mListener != null) {
mListener.onPermissionGranted();
}
}
} else {
if (mListener != null) {
mListener.onPermissionGranted();
}
}
}
/**
* 申请权限前判断是否需要声明
*
* @param desc
* @param permissions
* @param requestCode
*/
private void requestEachPermissions(String desc, String[] permissions, int requestCode) {
if (shouldShowRequestPermissionRationale(permissions)) {// 需要再次声明
showRationaleDialog(desc, permissions, requestCode);
} else {
ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
}
}
/**
* 弹出声明的 Dialog
*
* @param desc
* @param permissions
* @param requestCode
*/
private void showRationaleDialog(String desc, final String[] permissions, final int requestCode) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.tips))
.setMessage(desc)
.setPositiveButton(getResources().getString(R.string.confrim), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
}
})
.setNegativeButton(getResources().getString(R.string.cancle), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setCancelable(false)
.show();
}
/**
* 再次申请权限时,是否需要声明
*
* @param permissions
* @return
*/
private boolean shouldShowRequestPermissionRationale(String[] permissions) {
for (String permission : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
return true;
}
}
return false;
}
/**
* 检察每个权限是否申请
*
* @param permissions
* @return true 需要申请权限,false 已申请权限
*/
private boolean checkEachSelfPermission(String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
/**
* 申请权限结果的回调
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == mRequestCode) {
if (checkEachPermissionsGranted(grantResults)) {
if (mListener != null) {
mListener.onPermissionGranted();
}
} else {// 用户拒绝申请权限
if (mListener != null) {
mListener.onPermissionDenied();
}
}
}
}
/**
* 检查回调结果
*
* @param grantResults
* @return
*/
private boolean checkEachPermissionsGranted(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
}

每一个方法都有注释,逻辑也相对简单,就是我会遍历每个数组中申请的权限,如果需要申请就去申请,然后再处理一下回调的结果,其中还有对用户拒绝,然后再次申请弹出 Dialog 的处理。

如果在 Fragment 中使用,只是改变了一下参数封到 BaseFragment 中,这里就不贴代码了,都已经上传 github

BaseActivity:

BuzzerBeater BaseActivity

BaseFragment:

BuzzerBeater BaseFragment

如有问题,继续交流~